#region MIT Licence
/*
 * Copyright (C) 2014 PdfCreative
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
 * and associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom 
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included 
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace PdfCreative.Pdf.Writer.Utilities
{
    /// <summary>
    /// The PdfUtilities class is a static library class that contains convenience methods that facilitate the
    /// Writer and its assorted classes.
    /// </summary>
    public static class PdfUtilities
    {
        // Public methods
        // ==============
        #region Public methods
        /// <summary>
        /// Retrieves the string value of the specified object instance.
        /// If the value is a dictionary (implements the IDictionary interface) then the result will be a PDF-style dictionary, including
        /// the dictionary start and end tokens (&lt;&lt;, &gt;&gt;).
        /// If the value is a list (implements the IList interface) then the result will be a PDF-style array of the form
        /// "[ n0 n1 n2 ... ]" where n0 etc refer to items in the list.
        /// Each item in a list or dictionaryt is appended using the result of GetPdfStringValue() of that value, so it is possible for
        /// dictionaries and lists to contain further dictionaries or lists. The keys in a dictionary entry are not evaluated in this way;
        /// instead, the results of their ToString() methods are used.
        /// For all other values, the string is the result of the object's ToString() method.
        /// </summary>
        /// <param name="value">The object instance</param>
        /// <returns>The object's string value. If the object instance is null, the string value will be null as well.</returns>
        public static string GetPdfStringValue(object value)
        {
            string returnValue = null;
            if (null != value)
            {
                if (value is string) returnValue = (string)value;
                else if (value is IDictionary)
                {
                    // If this is a dictionary we output a PDF dictionary.
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("<<");
                    foreach (DictionaryEntry entry in (IDictionary)value)
                        sb.AppendFormat("/{0}\t\t{1}\r\n", entry.Key, GetPdfStringValue(entry.Value));
                    sb.Append(">>");
                    returnValue = sb.ToString();
                }
                else if (value is IList)
                {
                    // If this is a dictionary we output a PDF dictionary.
                    StringBuilder sb = new StringBuilder();
                    sb.Append("[");
                    foreach(object obj in(IList)value)
                        sb.AppendFormat(" {0}",GetPdfStringValue(obj));
                    sb.Append("]");
                    returnValue = sb.ToString();
                }
                else returnValue = value.ToString();
            }

            return returnValue;
        } // GetPdfStringValue()

        /// <summary>
        /// Escapes the specified string for use in a PDF DrawText() operation. All characters above ASCII 127 are escaped, as well
        /// as the (, ) and \ characters. This method does not support unicode tokens. All characters are converted into
        /// the default Windows ANSI encoding.
        /// </summary>
        /// <param name="text">The text</param>
        /// <returns></returns>
        public static string EscapeString(string text)
        {
            StringBuilder sb = new StringBuilder();

            // Encode the string to the default Window ANSI code page.
            byte[] bytes = System.Text.ASCIIEncoding.Default.GetBytes(text);

            int ch;
            for (int index = 0; index < bytes.Length; index++)
            {
                ch = bytes[index];
                if (ch >= 128)
                {
                    sb.Append('\\').Append(Convert.ToString(ch, 8));
                }
                else if (ch == 40 || ch == 41) sb.Append("\\0").Append(Convert.ToString((int)ch, 8));
                else if (ch == 92) sb.Append("\\").Append(Convert.ToString((int)ch, 8));
                else sb.Append((char)ch);
            }
            return sb.ToString();
        }
        #endregion

    } // PdfUtilities class
}
